<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="战棋游戏开发前言 该系列文章为本人开发战棋游戏的回顾总结。  开发工具下面是游戏开发使用的引擎和框架。 游戏引擎: Unity3D 游戏框架: GameFramework  游戏源码 系统整体结构 系统整体结构 战棋战斗系统 战场地图模块 战斗单位模块 战斗流程模块   战斗编辑器系统 地图数据编辑器 战斗数据编辑器   其他辅助功能模块战场地图模块   战场地图设置为六边形网格地图, 使用字典保">
<meta property="og:type" content="article">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="战棋游戏开发前言 该系列文章为本人开发战棋游戏的回顾总结。  开发工具下面是游戏开发使用的引擎和框架。 游戏引擎: Unity3D 游戏框架: GameFramework  游戏源码 系统整体结构 系统整体结构 战棋战斗系统 战场地图模块 战斗单位模块 战斗流程模块   战斗编辑器系统 地图数据编辑器 战斗数据编辑器   其他辅助功能模块战场地图模块   战场地图设置为六边形网格地图, 使用字典保">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/d9f28627a058449caabd869cc4048f85.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/61938cf1e62f486eb01ce5dbe01cb8c7.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/a3696354ff4d451cbe00b919097c1392.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/81cacdddabf042338a0a93e91702c002.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/6e5be01e0fc546019f97e249e8ea719e.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/4b2e79dad1b34385933d0a63e8dab15a.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/7f14c15f565a4113a3ae2570c096d00c.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/cc92ad6c143f41d781dcc881b3e17781.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/26c3571b72b74b94958f110e2eece9ae.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/81460e4a6e244b5d86a963070ef2a252.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/11.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/新建动作控制器-1651409549478.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/初始化地形.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/初始化地形%20(2">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/reprint.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/newCurrentTime2.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/articleReadEyes2.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/tobarCollect2.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/销毁子弹.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/istag.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/地图障碍物创建.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220515191812531.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220515211458145.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220522231458239.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220523010831259.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220523011930468.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/43b38a851ba7dd93e9c84a8bdb0f4bb186f4cf0a.jpg@942w_569h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/b1992e00cd18c063c49fb763a3de709d38a59e69.jpg@942w_546h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/776f3da73668fa8d6ed0274a921b38d97a3487e2.jpg@770w_1203h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/4b95d5881b702068519140124277043ac05128ac.jpg@942w_510h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/541f40abd2916243a2209e2436c726cfa7aec1c6.jpg@942w_467h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/57613e935ddffe892af08546ba4dfadf08b5b06a.jpg@942w_531h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/3852e58f4d0fe6944369b0194e48929803881b62.jpg@942w_546h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/8c2b359a6d0c3f9bda5c0af169caf9ee059fda56.jpg@942w_546h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/eb6fd6fe479d0369cd41051ef763f5251f241fef.jpg@942w_546h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/838cdb52133477b458b719b5176a1db82cac17a2.jpg@942w_512h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/6fbfd68ca128466f8ff767a47cc21e2e67d4ecda.jpg@942w_543h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/2c9882c0941ae016cc49b1e0d415f6301a8a8792.jpg@942w_534h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/4b0a8665877a6db35906d5c3490807a4e608dc55.jpg@942w_647h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/bfeaed96e57cc3448e4afb41fd87c2873a35267f.jpg@942w_534h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/afe4c8be6b7dd1de73b048a42f384b5e2cee0f68.jpg@942w_642h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/bec33ec8b86a57c4b18e0bb612ba21707693b349.jpg@942w_347h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/62b3228f3b568974af150ce9e1883c058faeffc1.jpg@942w_546h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/2be2000841d92611d502967481f262305b356f1c.jpg@942w_807h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/e9aa69df640d1dc5fb3ff99bc2dbbe37aa33a86e.png@942w_531h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/5222ae2b097e5c795c12dfed90804e4cb39a0ef4.png@942w_531h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/ddddc7107acbf24518168c3054bf6234c1a2321d.png@942w_531h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/d3e6e5a570df11ca1c22cf607532ec18a163c70e.png@942w_531h_progressive.webp">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220603230939765.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220603230957171.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/v2-998ea4beb691e080fb40d892db88165d_720w.jpg">
<meta property="og:image" content="file:///C:/Users/admin/AppData/Roaming/Tencent/Users/1399130811/QQ/WinTemp/RichOle/821K(9G_L@R3HT(LDAF9V70.png">
<meta property="og:image" content="c:/Users/admin/Desktop/821K(9G_L@R3HT(LDAF9V70.png">
<meta property="og:image" content="c:/Users/admin/Desktop/821K(9G_L@R3HT(LDAF9V70.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/sdf.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220604125533161.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220604133218784.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/image-20220604133606275.png">
<meta property="og:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/]HHLV8%SMAX$%7BSOU%7BIDOBCC.png">
<meta property="article:published_time" content="2022-03-08T12:52:04.204Z">
<meta property="article:modified_time" content="2022-06-04T07:07:52.421Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/d9f28627a058449caabd869cc4048f85.png">
  
    <link rel="alternate" href="/notes-on-computer-expertise/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/notes-on-computer-expertise/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/notes-on-computer-expertise/css/style.css">

  
    
<link rel="stylesheet" href="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/notes-on-computer-expertise/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/">Home</a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/notes-on-computer-expertise/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://goofyer.gitee.io/notes-on-computer-expertise"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-炉石传说/第一步开发游戏选择界面 - 副本" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/" class="article-date">
  <time class="dt-published" datetime="2022-03-08T12:52:04.204Z" itemprop="datePublished">2022-03-08</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="战棋游戏开发"><a href="#战棋游戏开发" class="headerlink" title="战棋游戏开发"></a><strong>战棋游戏开发</strong></h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><ul>
<li>该系列文章为本人开发战棋游戏的回顾总结。</li>
</ul>
<h2 id="开发工具"><a href="#开发工具" class="headerlink" title="开发工具"></a>开发工具</h2><h3 id="下面是游戏开发使用的引擎和框架。"><a href="#下面是游戏开发使用的引擎和框架。" class="headerlink" title="下面是游戏开发使用的引擎和框架。"></a>下面是游戏开发使用的引擎和框架。</h3><ul>
<li>游戏引擎: Unity3D</li>
<li>游戏框架: GameFramework</li>
</ul>
<p>游戏源码</p>
<h2 id="系统整体结构"><a href="#系统整体结构" class="headerlink" title="系统整体结构"></a>系统整体结构</h2><ul>
<li>系统整体结构<ul>
<li>战棋战斗系统<ul>
<li>战场地图模块</li>
<li>战斗单位模块</li>
<li>战斗流程模块</li>
</ul>
</li>
<li>战斗编辑器系统<ul>
<li>地图数据编辑器</li>
<li>战斗数据编辑器</li>
</ul>
</li>
<li>其他辅助功能模块<h3 id="战场地图模块"><a href="#战场地图模块" class="headerlink" title="战场地图模块"></a>战场地图模块</h3></li>
</ul>
</li>
<li>战场地图设置为六边形网格地图, 使用字典保存地图网格单元数据。</li>
<li>战场生成步骤:<ul>
<li>反序列化战场地图数据 - 借助newtonsoft.json</li>
<li>战场地图渲染 - 借助Unity组件tilemap<h3 id="人物模型搭建"><a href="#人物模型搭建" class="headerlink" title="人物模型搭建"></a>人物模型搭建</h3><h4 id="首先我们先把玩家导入进去"><a href="#首先我们先把玩家导入进去" class="headerlink" title="首先我们先把玩家导入进去"></a>首先我们先把玩家导入进去</h4>现在市面上公开的模型好多都是pmx，我们要先进行转码成fbx，这就需要用到blender<br>下载网址：<br><a target="_blank" rel="noopener" href="https://www.blender.org/download/lts/2-83/">Blender 2.83 LTS — blender.org</a><br><a href="https://codeload.[github](https://so.csdn.net/so/search?q=github&amp;spm=1001.2101.3001.7020).com/GiveMeAllYourCats/cats-blender-plugin/zip/master">https://codeload.[github](https://so.csdn.net/so/search?q=github&amp;spm=1001.2101.3001.7020).com/GiveMeAllYourCats/cats-blender-plugin/zip/master</a><br>三、Blender安装好和下载好插件之后，打开Blender安装插件<br>依次点击  编辑-&gt;偏好设置-&gt;插件-&gt;安装  选在刚才下好的插件压缩包进行安装。<br><img src="d9f28627a058449caabd869cc4048f85.png" alt="img"><br>四、安装后打开软件右上角的小箭头<br><img src="61938cf1e62f486eb01ce5dbe01cb8c7.png" alt="img"><br>五、选择CAST选项，选择MMD，然后选择需要转换的PMX文件<br><img src="a3696354ff4d451cbe00b919097c1392.png" alt="img"><br>六、打开模型后，选择杂项-&gt;Shadeless<br><img src="81cacdddabf042338a0a93e91702c002.png" alt="img"><br>七、回到CAST选项，修改Fix Model（点击Fix Model右边的把手）<br><img src="6e5be01e0fc546019f97e249e8ea719e.png" alt="img"><br>八 、修改完成后点击Fix Model，等待数十秒。<br><img src="4b2e79dad1b34385933d0a63e8dab15a.png" alt="img"><br>九、完成后，就可以点击导出模型了（Export Model）<br><img src="7f14c15f565a4113a3ae2570c096d00c.png" alt="img"><br>十、导出成FBX格式后，先把相关贴图文件夹先导入/拖入Unity，之后才能把FBX模型导入/拖入。否则导入的会只是一个白模。<br>十一、正常导入后会如红框中显示的没有相关 材质，这时需要点击Extract Materials，之后会自动匹配上。<br><img src="cc92ad6c143f41d781dcc881b3e17781.png" alt="img"><img src="26c3571b72b74b94958f110e2eece9ae.png" alt="img"><br>十三、至此已经完成导入，如模型出现异常请先检查相关材质是否已经先导入了，并且和原来PMX模型相对目录结构一致。 已导入的话，将材质的渲染模式改成Cutout。<br><img src="81460e4a6e244b5d86a963070ef2a252.png" alt="img"></li>
</ul>
</li>
</ul>
<p>一、给人物模型添加对应的动作模型</p>
<p><img src="11.png" alt="11"></p>
<p>二、新建动作控制器</p>
<p><img src="新建动作控制器-1651409549478.png" alt="新建动作控制器"></p>
<p>三、初始化地形</p>
<p><img src="初始化地形.png" alt="初始化地形"></p>
<p><img src="初始化地形 (2" alt="初始化地形 (2)">.png)</p>
<p>编写摄像头移动脚本</p>
<p>补充下基础知识</p>
<h1 id="Unity3D入门篇——Transform类"><a href="#Unity3D入门篇——Transform类" class="headerlink" title="Unity3D入门篇——Transform类"></a>Unity3D入门篇——Transform类</h1><p><img src="reprint.png" alt="img"></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/a_little_a_day">a_little_a_day</a><img src="newCurrentTime2.png" alt="img">于 2018-03-01 11:30:30 发布<img src="articleReadEyes2.png" alt="img">3533<img src="tobarCollect2.png" alt="img"> 收藏 6</p>
<p><strong>Unity3D入门篇——Transform类</strong></p>
<p>Transform组件是Unity3D的重点之一，主要用于控制物体的旋转、移动、缩放。那么接下来我们将详细学习下Transform类所包含的成员变量和<a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=成员函数&amp;spm=1001.2101.3001.7020">成员函数</a>。</p>
<p><strong>一、成员变量</strong></p>
<p><strong>position：在世界空间坐标transform的位置。<br>localPosition：相对于父级的变换的位置。如果该变换没有父级，那么等同于Transform.position。<br>eulerAngles：世界坐标系中的旋转（欧拉角）。<br>localEulerAngles：相对于父级的变换旋转角度。<br>right：世界坐标系中的右方向。（世界空间坐标变换的红色轴。也就是x轴。）<br>up：世界坐标系中的上方向。（在世界空间坐标变换的绿色轴。也就是y轴。）<br>forward：世界坐标系中的前方向。（在世界空间坐标变换的蓝色轴。也就是z轴。）<br>rotation：世界坐标系中的旋转（四元数）。<br>localRotation：相对于父级的变换旋转角度。<br>localScale：相对于父级的缩放比例。<br>parent：父对象Transform组件。<br>worldToLocalMatrix：矩阵变换的点从世界坐标转为自身坐标（只读）。<br>localToWorldMatrix：矩阵变换的点从自身坐标转为世界坐标（只读）。<br>root：对象层级关系中的根对象的Transform组件。<br>childCount：子对象数量。<br>lossyScale：全局缩放比例（只读）。
</strong></p>
<p><strong>二、成员函数：</strong></p>
<p><strong>1、LookAt函数</strong></p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> <strong>void</strong> LookAt(Transform target) </li>
<li><strong>public</strong> <strong>void</strong> LookAt(Vector3 worldPosition); </li>
<li><strong>public</strong> <strong>void</strong> LookAt(Vector3 worldPosition, Vector3 worldUp = Vector3.up); </li>
<li><strong>public</strong> <strong>void</strong> LookAt(Transform target, Vector3 worldUp = Vector3.up); </li>
</ol>
<p>旋转物体，使物体的z轴指向target/worldPosition，对于worldUp的描述是，在完成上面的旋转之后，继续旋转自身，使得当前对象的正y轴朝向与worldUp所指向的朝向一致。</p>
<p>这里的朝向一致指的是新旋转后的y轴与worldUp在该对象初次旋转后的xy平面上的投影向量一致。之所以取投影是因为第一次旋转使物体的z轴指向target/worldPosition后，此时的worldUp向量可能不在xy平面上，要在z轴指向target/worldPosition前提下是y轴朝向与worldUp一致，只能取worldUp在xy平面上的投影。</p>
<p>注意：使用worldPosition向量时要注意方向，一定是target-transform.position，顺序反了会使物体背向目标；若使用Transform作为参数，则不必注意。默认情况下，worldUp是Vector3.up（世界坐标系下的y轴）</p>
<p><strong>2、Rotate函数</strong></p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> <strong>void</strong> Rotate(Vector3 eulerAngles); </li>
<li><strong>public</strong> <strong>void</strong> Rotate(Vector3 eulerAngles, Space relativeTo = Space.Self); </li>
<li><strong>public</strong> <strong>void</strong> Rotate(<strong>float</strong> xAngle, <strong>float</strong> yAngle, <strong>float</strong> zAngle); </li>
<li><strong>public</strong> <strong>void</strong> Rotate(<strong>float</strong> xAngle, <strong>float</strong> yAngle, <strong>float</strong> zAngle, Space relativeTo = Space.Self); </li>
</ol>
<p>旋转一个欧拉角度，它按照zxy的顺序进行旋转，默认情况下局部坐标系下Space.Self。</p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> <strong>void</strong> Rotate(Vector3 axis, <strong>float</strong> angle);       </li>
<li><strong>public</strong> <strong>void</strong> Rotate(Vector3 axis, <strong>float</strong> angle,Space relativeTo = Space.Self); </li>
</ol>
<p>绕axis轴旋转angle角度，默认情况下局部坐标系下Space.Self。</p>
<p><strong>transform.rotation和Rotate有个区别：</strong></p>
<p>Rotate()方法是：旋转多少度。在原有的基础上累加，即旋转了多少角度。又旋转了多少角度，是在原有的基础上在旋转</p>
<p>rotation属性是：旋转到某个角度，就是是在update中每帧都执行。但每次旋转到的角度都是5，所以是旋转到5度。一直都是</p>
<p>比如你只想让他旋转到多少, 用rotation; 假如想让他一直转,可以用Rotate</p>
<p>rotation直接改变了数值, 以达到旋转效果</p>
<p>Rotate应用一个的旋转角度每秒1度慢慢的旋转物体</p>
<p>当然:rotation()还可以通过插值旋转</p>
<p><strong>3、TransformDirection函数</strong></p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> Vector3 TransformDirection(Vector3 direction); </li>
<li><strong>public</strong> Vector3 TransformDirection(<strong>float</strong> x, <strong>float</strong> y, <strong>float</strong> z); </li>
</ol>
<p>从自身坐标到世界坐标变换方向（这个强调的是方向）这个操作不会受到变换的缩放和位置的影响。返回的向量与direction有同样的长度</p>
<p><strong>4、TransformPoint函数</strong></p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> Vector3 TransformPoint(Vector3 position); </li>
<li><strong>public</strong> Vector3 TransformPoint(<strong>float</strong> x, <strong>float</strong> y, <strong>float</strong> z); </li>
</ol>
<p>变换位置从自身坐标到世界坐标。注意，返回位置受缩放影响</p>
<p><strong>5、TransformVector函数</strong></p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> Vector3 TransformVector(Vector3 vector); </li>
<li><strong>public</strong> Vector3 TransformVector(<strong>float</strong> x, <strong>float</strong> y, <strong>float</strong> z); </li>
</ol>
<p>变换一个向量从局部坐标空间到世界坐标空间。这个操作不受变换位置的影响，但是受缩放的影响</p>
<p><strong>6、Translate函数</strong></p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> <strong>void</strong> Translate(Vector3 translation); </li>
<li><strong>public</strong> <strong>void</strong> Translate(Vector3 translation, Space relativeTo = Space.Self); </li>
</ol>
<p>沿着translation方向移动translation向量长度的距离,如果relativeTo留空或者设置为Space.Self，移动被应用相对于自身坐标系</p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> <strong>void</strong> Translate(<strong>float</strong> x, <strong>float</strong> y, <strong>float</strong> z); </li>
<li><strong>public</strong> <strong>void</strong> Translate(<strong>float</strong> x, <strong>float</strong> y, <strong>float</strong> z, Space relativeTo = Space.Self); </li>
</ol>
<p>移动变换由x沿着x轴，y沿着y轴，z沿着z轴。如果relativeTo留空或者设置为Space.Self，移动被应用相对于自身坐标系</p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><strong>public</strong> <strong>void</strong> Translate(Vector3 translation, Transform relativeTo);   </li>
<li><strong>public</strong> <strong>void</strong> Translate(<strong>float</strong> x, <strong>float</strong> y, <strong>float</strong> z, Transform relativeTo); </li>
</ol>
<p>第一个参数的解释跟前面的一样，重点在移动relativeTo，解释为被应用相对于（relativeTo :Transform）的自身坐标系统。日光相对于为null，则移动被应用相对于世界坐标系统</p>
<p><strong>[csharp]</strong> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">view plain</a> <a target="_blank" rel="noopener" href="http://blog.csdn.net/u014086857/article/details/53091268#">copy</a></p>
<ol>
<li><p>例子： </p>
</li>
<li><p><strong>void</strong> Update() </p>
</li>
<li><p>{ </p>
</li>
<li><p>//相对于摄像机每秒1单位向右移动物体 </p>
</li>
<li><p>transform.Translate(Vector3.right * Time.deltaTime, Camera.main.transform); </p>
</li>
<li><p>} </p>
</li>
</ol>
<p>第一步 编写接受键盘信息的方法<br>    void Update()<br>    {<br>        if (Input.geyKeyDown(KeyCode.A))<br>        {<br>            Debug.Log(“A”);<br>            //gameObject.transform.position;<br>        }<br>        if (Input.geyKeyDown(KeyCode.S))<br>        {<br>            Debug.Log(“S”);<br>            //gameObject.transform.position;<br>        }<br>        if (Input.geyKeyDown(KeyCode.D))<br>        {<br>            Debug.Log(“D”);<br>            //gameObject.transform.position;<br>        }<br>        if (Input.geyKeyDown(KeyCode.W))<br>        {<br>            Debug.Log(“W”);<br>            //gameObject.transform.position;<br>        }<br>    }</p>
<p>第二步 添加摄像机位移方法</p>
<p>补充知识：</p>
<pre><code>    Vector3.forward                (前方)
    Vector3.up                        (上方)
    Vector3.right                   （右方）

    Vector3.back                     (后方)
    Vector3.left                        (左方）
    Vector3.down                    (下方)
void Update()
&#123;
    if (Input.GetKey(KeyCode.A))
    &#123;
        Debug.Log(&quot;A&quot;);
        this.transform.Translate(Vector3.left * Time.deltaTime * speed);
        //gameObject.transform.position;
    &#125;
    if (Input.GetKey(KeyCode.S))
    &#123;
        Debug.Log(&quot;S&quot;);
        this.transform.Translate(Vector3.back * Time.deltaTime * speed);
        //gameObject.transform.position;
    &#125;
    if (Input.GetKey(KeyCode.D))
    &#123;
        Debug.Log(&quot;d&quot;);
        this.transform.Translate(Vector3.right*Time.deltaTime*speed);
    &#125;
    if (Input.GetKey(KeyCode.W))
    &#123;
        Debug.Log(&quot;W&quot;);
        this.transform.Translate(Vector3.forward * Time.deltaTime * speed);
        //gameObject.transform.position;
    &#125;
&#125;
</code></pre><p>然后添加可以在鼠标光标位置放置角色的方法</p>
<pre><code>    if (Input.GetMouseButtonUp(0))
    &#123;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (Physics.Raycast(ray, out hit))
        &#123;
            Debug.Log(hit.point);
            Instantiate(people, hit.point, people.transform.rotation);
        &#125;
    &#125;
</code></pre><p>编写角色攻击方法</p>
<p>角色攻击一般分为近战和远程，我们先实现远程的角色</p>
<p>第一步 先实现点击键盘e键对应角色发射子弹的方法</p>
<p>public class PersonShut : MonoBehaviour<br>{<br>    // 射击物<br>    public GameObject ShutObject;<br>    // Start is called before the first frame update<br>    /// <summary>
    /// 子弹持续时间
    /// </summary><br>    private int time;<br>    // Start is called before the first frame update<br>    void Start()<br>    {<br>        Destroy(ShutObject, time);<br>    }</p>
<pre><code>void Update()
&#123;
    if (Input.GetKeyUp(KeyCode.E))
    &#123;
        Debug.Log(&quot;发射&quot;);
        var people = this.transform.rotation.eulerAngles;
        var shutPosition = this.transform.position;
        shutPosition += new Vector3(
            2 * (float)Math.Sin(people.y / 180 * Math.PI),
            10,
            2 * (float)Math.Cos(people.y / 180 * Math.PI));
        //shutPosition+= this.transform.rotation * 3;
        Instantiate(ShutObject, shutPosition, this.transform.rotation);
    &#125;
&#125;
</code></pre><p>}</p>
<p>第二步 编写子弹脚本</p>
<p>public class ShutBomb : MonoBehaviour<br>{<br>    public GameObject Person;<br>    // 射击物<br>    public GameObject ShutObject;<br>    /// <summary>
    /// 子弹持续时间
    /// </summary><br>    public int time;<br>    public int forceNum;<br>    // Start is called before the first frame update<br>    void Start()<br>    {<br>        Vector3 angle = Person.transform.rotation.eulerAngles;<br>        Vector3 Force = new Vector3(forceNum <em> (float)Math.Sin(angle.y / 180 </em> Math.PI), 2, forceNum <em> (float)Math.Cos(angle.y / 180 </em> Math.PI));<br>        ShutObject.GetComponent<Rigidbody>().AddForce(Force, ForceMode.VelocityChange);<br>    }<br>    void OnBecameInvisible()<br>    {<br>        if (this.enabled)<br>        {<br>            Destroy(this.gameObject);<br>        }<br>    }<br>    // Update is called once per frame<br>    void Update()<br>    {<br>    }<br>}</p>
<p>编写子弹消失方法</p>
<p>public class DelectShut : MonoBehaviour<br>{<br>    public GameObject shut;<br>    // Start is called before the first frame update<br>    void Start()<br>    {<br>        Destroy(shut, 5);<br>    }</p>
<pre><code>// Update is called once per frame
void Update()
&#123;

&#125;
</code></pre><p>}</p>
<p>然后将其挂载在子弹上</p>
<p><img src="销毁子弹.png" alt="销毁子弹"></p>
<p>增添子弹击中目标爆炸方法</p>
<p>在子弹预制体上选择Is Trigger选项</p>
<p><img src="istag.png" alt="istag"></p>
<p>下一步 设计场景地图</p>
<p>第一步 创建单个地图元</p>
<p><img src="地图障碍物创建.png" alt="地图障碍物创建"></p>
<p>添加贴图</p>
<p><img src="image-20220515191812531.png" alt="image-20220515191812531"></p>
<p><em>A在此球体上显示为反射的山脉场景立方体贴图 (Cubemap)</em></p>
<p>可以通过多种方式之一创建立方体贴图 (Cubemap)：</p>
<ol>
<li>使用 (Assets)-&gt;创建 (Create)-&gt;立方体贴图 (Cubemap),设置其属性，然后将六个<a target="_blank" rel="noopener" href="https://www.wenjiangs.com/doc/8cmt2UC9">纹理(Texture)</a> 资源拖动到对应立方体贴图 (Cubemap)“面”上。请注意，纹理在更改时必须重新应用，因为纹理会烘焙为立方体贴图资源 (Cubemap Asset)，无法链接到纹理。</li>
<li>使用<a target="_blank" rel="noopener" href="https://www.wenjiangs.com/doc/8cmt2UC9">纹理(Texture)</a> 导入设置从导入的单个纹理资源创建立方体贴图 (Cubemap)。</li>
<li>从脚本将场景渲染为立方体贴图 (Cubemap)。 Camera.RenderToCubemap 页面中的代码示例包含用于从编辑器直接渲染立方体贴图 (Cubemap) 的脚本。</li>
</ol>
<h2 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h2><div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:left">属性：</th>
<th style="text-align:left">功能：</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">右 (+X) (Right (+X))</td>
<td style="text-align:left">立方体贴图 (Cubemap) 面右全局面的纹理。</td>
</tr>
<tr>
<td style="text-align:left">左 (-X) (Left (-X))</td>
<td style="text-align:left">立方体贴图 (Cubemap) 面上全局面的纹理。</td>
</tr>
<tr>
<td style="text-align:left">上 (+Y) (Top (+Y))</td>
<td style="text-align:left">立方体贴图 (Cubemap) 面上全局面的纹理。</td>
</tr>
<tr>
<td style="text-align:left">下 (-Y) (Bottom (-Y))</td>
<td style="text-align:left">立方体贴图 (Cubemap) 面下全局面的纹理。</td>
</tr>
<tr>
<td style="text-align:left">前 (+Z) (Front (+Z))</td>
<td style="text-align:left">立方体贴图 (Cubemap) 面前全局面的纹理。</td>
</tr>
<tr>
<td style="text-align:left">后 (-Z) (Front (-Z))</td>
<td style="text-align:left">立方体贴图 (Cubemap) 面后全局面的纹理。</td>
</tr>
<tr>
<td style="text-align:left">面大小 (Face Size)</td>
<td style="text-align:left">每个单独立方体贴图 (Cubemap) 面的宽度和高度（以像素为单位）。纹理会在内部缩放以适应此大小，无需手动缩放资源。</td>
</tr>
<tr>
<td style="text-align:left">多层贴图 (Mipmap)</td>
<td style="text-align:left">启用可创建多层贴图。</td>
</tr>
<tr>
<td style="text-align:left">格式 (Format)</td>
<td style="text-align:left">创建的立方体贴图 (Cubemap) 的格式。</td>
</tr>
</tbody>
</table>
</div>
<p><img src="image-20220515211458145.png" alt="image-20220515211458145"></p>
<p>将其绑定到这个位置 并设计好参数</p>
<p>public class MapCreate : MonoBehaviour<br>{<br>    /// <summary>
    /// 关卡数
    /// </summary><br>    public int Level;<br>    public int[,,] map = new int[1, 10, 10]<br>        {<br>            {<br>                {1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },<br>                {1, 1, 1,-1,-1,-1,-1,-1,-1, 1 },<br>                {1,-1,-1,-1, 1,-1, 1, 1, 1, 1 },<br>                {1, 1,-1,-1,-1,-1,-1,-1,-1, 1 },<br>                {1, 1, 1, 1, 1,-1,-1,-1,-1, 1 },<br>                {1,-1,-1,-1,-1,-1,-1,-1,-1, 1 },<br>                {1, 1, 1,1,1,1,1,1,1,1 },<br>                {1, 1, 1,1,1,1,1,1,1,1 },<br>                {1, 1, 1,1,1,1,1,1,1,1 },<br>                {1, 1, 1,1,1,1,1,1,1,1 }<br>            }<br>        };<br>    public GameObject road1;<br>    public GameObject obstacle1;<br>    public int width, high;<br>    // Start is called before the first frame update<br>    void Start()<br>    {<br>        for(int i=0;i&lt;width;i++)<br>            for(int j=0;j&lt;high;j++)<br>            {<br>                if (map[0, i, j] == 1)<br>                    Instantiate(obstacle1, new Vector3(10 <em> i, 5,10  </em> j), new Quaternion(0, 0, 0, 0));<br>                else if (map[0, i, j] == -1)<br>                    Instantiate(road1, new Vector3(10  <em> i, 5, 10 </em> j), new Quaternion(0, 0, 0, 0));<br>            }<br>    }</p>
<pre><code>// Update is called once per frame
void Update()
&#123;

&#125;
</code></pre><p>}</p>
<p>或则手工放置地图方块</p>
<p>cube添加贴图方法</p>
<p><strong>blender 创建具有贴图材质的模型，导入到Unity中</strong></p>
<p>环境：<br>win10<br>blender 2.79<br>unity 5.8.2</p>
<p>一、新建一个cube</p>
<p><img src="image-20220522231458239.png" alt="image-20220522231458239"></p>
<p>1.打开一个UV图像编辑器窗口</p>
<p><img src="image-20220523010831259.png" alt="image-20220523010831259"></p>
<p>2.在三维视图按Tab进入编辑模式</p>
<p>3.按U键调出菜单，选第二项点确定</p>
<p><img src="image-20220523011930468.png" alt="image-20220523011930468"></p>
<p>三、加贴图<br>1.打开一张图（我随便找了一张）</p>
<p>地图编辑器感谢<a target="_blank" rel="noopener" href="https://space.bilibili.com/2059519">梦符佳月</a></p>
<p><strong>使用方法：</strong></p>
<p>1.在Excel中输入地形编号，绘制关卡平面图</p>
<p><img src="43b38a851ba7dd93e9c84a8bdb0f4bb186f4cf0a.jpg@942w_569h_progressive.webp" alt="img"></p>
<p>例如上图，敌人将从红色方格（0）进入战场，走过黄色方格（2）（3），最终进入蓝色方格（1）。</p>
<p>玩家可以在（2）（4）上布置干员建立防守阵线。</p>
<p>如果敌人被移动至（6）中，则原地去世。</p>
<p>（7）是地图边沿，大型的配景模型将放置于此。</p>
<p>据此，相信游玩过《明日方舟》的网友可以在脑海中构建出关卡的大致样式。</p>
<p>之后，在保持excel开启的状态下，打开rhino，打开文件“地图样板”</p>
<p><img src="b1992e00cd18c063c49fb763a3de709d38a59e69.jpg@942w_546h_progressive.webp" alt="img">这个文件里没有几何物件，但是预先分好了图层，区别了材质，设立了几个视角</p>
<p>打开Grasshopper，打开文件“地图制作器”</p>
<p><img src="776f3da73668fa8d6ed0274a921b38d97a3487e2.jpg@770w_1203h_progressive.webp" alt="img">文末有源文件下载，截图就随便一点了</p>
<p>点击位于左上角的“读取表格”按钮，并调整读取的工作表序号和行列范围</p>
<p><img src="4b95d5881b702068519140124277043ac05128ac.jpg@942w_510h_progressive.webp" alt="img"></p>
<p>之后启用标有“预览”的电池Custom Preview，就可以在rhino中看到关卡预览</p>
<p>浅黄色部分是可以放置干员的地形，灰色的则相反。</p>
<p>如果对关卡设计不满意，可以在excel中修改</p>
<p><img src="541f40abd2916243a2209e2436c726cfa7aec1c6.jpg@942w_467h_progressive.webp" alt="img">使用条件格式，使单元格背景颜色随数值变化，便于查看。数值是控制地形的关键，颜色不是。</p>
<p>修改完成后，回到grasshopper，点击“读取表格”即可看到修改成果</p>
<p><img src="57613e935ddffe892af08546ba4dfadf08b5b06a.jpg@942w_531h_progressive.webp" alt="img"></p>
<p>之后，禁用标有“预览”的电池Custom Preview，点击“生成模型”按钮，即可完成建模。</p>
<p><img src="3852e58f4d0fe6944369b0194e48929803881b62.jpg@942w_546h_progressive.webp" alt="img"></p>
<p>之后，切换为渲染模式，获得更佳观看体验</p>
<p><img src="8c2b359a6d0c3f9bda5c0af169caf9ee059fda56.jpg@942w_546h_progressive.webp" alt="img"></p>
<p><strong>说明：</strong></p>
<p>1.流程概况</p>
<p>所有几何物件均为网格，整个过程大量数学运算，少量曲线布尔，基本不含物理运算，因此生成速度很快。生成上图所示模型，用时不到1秒。</p>
<p>2.数据流向</p>
<p>“预览”部分的参数、数据和最终生成的模型参数、数据不互通。</p>
<p>在点击“生成模型”之前，下半部分所有电池都不会收到数据，请放心调整。</p>
<p>3.“配景”的分类方式</p>
<p>（7）被我分成了三部分：南，北，和两侧，分离方法是这样的：</p>
<p><img src="eb6fd6fe479d0369cd41051ef763f5251f241fef.jpg@942w_546h_progressive.webp" alt="img"></p>
<p>若要调整分离方式，需要调整此滑杆：</p>
<p><img src="838cdb52133477b458b719b5176a1db82cac17a2.jpg@942w_512h_progressive.webp" alt="img"></p>
<p>4.特殊配景的出现规则</p>
<p>两侧建筑、白色铁架 是特殊的配景类物件，我设定了以下规则以让他们并不能总是出现，以保持配景的丰富度。</p>
<p>两侧建筑：对两侧的曲线进行布尔并集后，任意一边的长度都大于网格尺寸。</p>
<p>如下图所示，白色边框所示位置将出现建筑</p>
<p><img src="6fbfd68ca128466f8ff767a47cc21e2e67d4ecda.jpg@942w_543h_progressive.webp" alt="img"></p>
<p><img src="2c9882c0941ae016cc49b1e0d415f6301a8a8792.jpg@942w_534h_progressive.webp" alt="img"></p>
<p>下图所示情况则不会出现建筑，因为白色边框的区域，在布尔并集后，各曲线都至少有一条边是不大于网格尺寸的。</p>
<p><img src="4b0a8665877a6db35906d5c3490807a4e608dc55.jpg@942w_647h_progressive.webp" alt="img"></p>
<p><img src="bfeaed96e57cc3448e4afb41fd87c2873a35267f.jpg@942w_534h_progressive.webp" alt="img"></p>
<p>白色铁架：仅出现在南侧配景中，当且仅当有4个7相连时才会出现。</p>
<p><img src="afe4c8be6b7dd1de73b048a42f384b5e2cee0f68.jpg@942w_642h_progressive.webp" alt="img"></p>
<p><img src="bec33ec8b86a57c4b18e0bb612ba21707693b349.jpg@942w_347h_progressive.webp" alt="img"></p>
<p>其余所有配景或者同种地形的不同表现方式均为随机生成，可以通过调节参数进行控制。</p>
<p>5.所有的 调整是有意义的 参数滑杆我都放在cluster外面，并标上了注释。</p>
<p><img src="62b3228f3b568974af150ce9e1883c058faeffc1.jpg@942w_546h_progressive.webp" alt="img"></p>
<p>其中，标注有“1”“2”的滑杆，属于以下情况中的一种：</p>
<p><img src="2be2000841d92611d502967481f262305b356f1c.jpg@942w_807h_progressive.webp" alt="img"></p>
<p>功能相似的两个参数</p>
<p>有运算先后顺序的两个参数</p>
<p>一个区间的两个最值</p>
<p>6.必需的运行环境</p>
<p>rhino6.0</p>
<p>grasshopper1.0</p>
<p>插件 lunchbox（读取excel、自动bake、随机分组）</p>
<p>插件human（应用立方体贴图轴）</p>
<p>插件kangaroo2（删除重复直线、网格清理）</p>
<p>插件meshedit （炸开网格）</p>
<p>插件meshtool（网格管）</p>
<p><strong>文件下载：</strong></p>
<p>链接：<a target="_blank" rel="noopener" href="https://pan.baidu.com/s/1_2JzYxjxXiSdfOTIJytfHg">https://pan.baidu.com/s/1_2JzYxjxXiSdfOTIJytfHg</a></p>
<p>提取码：7nmp</p>
<p><strong>一些效果图</strong></p>
<p><img src="e9aa69df640d1dc5fb3ff99bc2dbbe37aa33a86e.png@942w_531h_progressive.webp" alt="img"></p>
<p><img src="5222ae2b097e5c795c12dfed90804e4cb39a0ef4.png@942w_531h_progressive.webp" alt="img"></p>
<p><img src="ddddc7107acbf24518168c3054bf6234c1a2321d.png@942w_531h_progressive.webp" alt="img"></p>
<p><img src="d3e6e5a570df11ca1c22cf607532ec18a163c70e.png@942w_531h_progressive.webp" alt="img"></p>
<p>设置敌人在起点创建（生命值）</p>
<p>设置敌人按轨迹移动</p>
<p>设置敌人终点消失</p>
<p>添加角色子弹与敌人的碰撞检测</p>
<p><img src="image-20220603230939765.png" alt="image-20220603230939765"></p>
<p><img src="image-20220603230957171.png" alt="image-20220603230957171"></p>
<p><strong>4.World: 多个地图块组成的世界，就是“我的世界”啦。</strong></p>
<p>我们可以看到这4个层次，其实有点类似俄罗斯套娃对吧，一层包含一层。</p>
<p>我们要生成World，那么就是要在这些层次中，一层一层的去处理生成的逻辑， 在World里动态加载Chunk, 在Chunk里生成Block, 在Block里生成Face。</p>
<p>1.首先我们先实现Chunk的生成，内部会包含 Block的生成，这里会用到simplex noise（一种Perlin噪声的改进）</p>
<p>有关噪声的知识，如果读者没有接触过，可以自行网上找找相关资料看看</p>
<p>这里推荐一篇（小姐姐写的比较细致）：<a href="https://link.zhihu.com/?target=http%3A//blog.csdn.net/candycat1992/article/details/50346469">【图形学】谈谈噪声 - candycat - CSDN博客</a></p>
<p>在这个部分我们会写一个类Chunk.cs, (大约200行代码)</p>
<p>2.接下来我们要通过玩家的位置信息来动态加载Chunk</p>
<p>这个部分我们会写一个类Player.cs (大约100行代码)</p>
<h2 id="Chunk生成"><a href="#Chunk生成" class="headerlink" title="Chunk生成"></a><strong>Chunk生成</strong></h2><p>首先新建一个Unity工程后，导入一些资源，资源包在这里下载：<a href="https://link.zhihu.com/?target=http%3A//pan.baidu.com/s/1hszPgwc">http://pan.baidu.com/s/1hszPgwc</a></p>
<p>接下来我们在场景中创建一个Cube</p>
<p>打开刚才新建的Chunk.cs，我们来先声明好Chunk类里需要用到的成员变量</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Chunk</span> : <span class="title">MonoBehaviour</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//Block的类型</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">enum</span> BlockType</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//空</span></span><br><span class="line">        None = <span class="number">0</span>,</span><br><span class="line">        <span class="comment">//泥土</span></span><br><span class="line">        Dirt = <span class="number">1</span>,</span><br><span class="line">        <span class="comment">//草地</span></span><br><span class="line">        Grass = <span class="number">3</span>,</span><br><span class="line">        <span class="comment">//碎石</span></span><br><span class="line">        Gravel = <span class="number">4</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//存储着世界中所有的Chunk</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="title">List</span>&lt;<span class="title">Chunk</span>&gt; chunks</span> = <span class="keyword">new</span> List&lt;Chunk&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//每个Chunk的长宽Size</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="built_in">int</span> width = <span class="number">30</span>;</span><br><span class="line">    <span class="comment">//每个Chunk的高度</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="built_in">int</span> height = <span class="number">30</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//随机种子</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">int</span> seed;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//最小生成高度</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">float</span> baseHeight = <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//噪音频率（噪音采样时会用到）</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">float</span> frequency = <span class="number">0.025f</span>;</span><br><span class="line">    <span class="comment">//噪音振幅（噪音采样时会用到）</span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">float</span> amplitude = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//存储着此Chunk内的所有Block信息</span></span><br><span class="line">    BlockType[,,] map;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//Chunk的网格</span></span><br><span class="line">    Mesh chunkMesh;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//噪音采样时会用到的偏移</span></span><br><span class="line">    Vector3 offset0;</span><br><span class="line">    Vector3 offset1;</span><br><span class="line">    Vector3 offset2;</span><br><span class="line"></span><br><span class="line">    MeshRenderer meshRenderer;</span><br><span class="line">    MeshCollider meshCollider;</span><br><span class="line">    MeshFilter meshFilter;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接下来，我们往这个类中加一些初始化的函数 如下：</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">Start</span> (<span class="params"></span>)</span></span><br><span class="line">   &#123;</span><br><span class="line">       <span class="comment">//初始化时将自己加入chunks列表</span></span><br><span class="line">       chunks.Add(<span class="keyword">this</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取自身相关组件引用</span></span><br><span class="line">meshRenderer = GetComponent&lt;MeshRenderer&gt;();</span><br><span class="line">meshCollider = GetComponent&lt;MeshCollider&gt;();</span><br><span class="line">meshFilter = GetComponent&lt;MeshFilter&gt;();</span><br><span class="line"></span><br><span class="line">       <span class="comment">//初始化地图</span></span><br><span class="line">       InitMap();</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">InitMap</span>(<span class="params"></span>)</span></span><br><span class="line">   &#123;</span><br><span class="line">       <span class="comment">//初始化随机种子</span></span><br><span class="line">       Random.InitState(seed);</span><br><span class="line">       offset0 = <span class="keyword">new</span> Vector3(Random.<span class="keyword">value</span> * <span class="number">1000</span>, Random.<span class="keyword">value</span> * <span class="number">1000</span>, Random.<span class="keyword">value</span> * <span class="number">1000</span>);</span><br><span class="line">       offset1 = <span class="keyword">new</span> Vector3(Random.<span class="keyword">value</span> * <span class="number">1000</span>, Random.<span class="keyword">value</span> * <span class="number">1000</span>, Random.<span class="keyword">value</span> * <span class="number">1000</span>);</span><br><span class="line">       offset2 = <span class="keyword">new</span> Vector3(Random.<span class="keyword">value</span> * <span class="number">1000</span>, Random.<span class="keyword">value</span> * <span class="number">1000</span>, Random.<span class="keyword">value</span> * <span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">       <span class="comment">//初始化Map</span></span><br><span class="line">       map = <span class="keyword">new</span> BlockType[width, height, width];</span><br><span class="line"></span><br><span class="line">       <span class="comment">//遍历map，生成其中每个Block的信息</span></span><br><span class="line">       <span class="keyword">for</span> (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; width; x++)</span><br><span class="line">       &#123;</span><br><span class="line">           <span class="keyword">for</span> (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; height; y++)</span><br><span class="line">           &#123;</span><br><span class="line">               <span class="keyword">for</span> (<span class="built_in">int</span> z = <span class="number">0</span>; z &lt; width; z++)</span><br><span class="line">               &#123;</span><br><span class="line">                   map[x, y, z] = GenerateBlockType(<span class="keyword">new</span> Vector3(x, y, z) + transform.position);</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       <span class="comment">//根据生成的信息，Build出Chunk的网格</span></span><br><span class="line">       BuildChunk();</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
<p>在上面这段代码中，我们需要注意两个点</p>
<p>1.这里的map存的是Chunk内每一个Block的信息</p>
<p>2.GenerateBlockType函数和BuildChunk函数，我们还没有实现</p>
<p>3.我们在Start函数被调用时，便将这个Chunk生成好了</p>
<p>在第二点中说的两个函数，便是我们接下来生成Chunk的两个核心步骤</p>
<p><strong>1.生成map信息（每个Block的类型，以及地形的高度信息）</strong></p>
<p><strong>2.构建Chunk用来显示的网格</strong></p>
<p>那么我们接下来分别看看如何实现这两步</p>
<p><strong>1.GenerateBlockType</strong></p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="built_in">int</span> <span class="title">GenerateHeight</span>(<span class="params">Vector3 wPos</span>)</span></span><br><span class="line">   &#123;</span><br><span class="line"></span><br><span class="line">       <span class="comment">//让随机种子，振幅，频率，应用于我们的噪音采样结果</span></span><br><span class="line">       <span class="built_in">float</span> x0 = (wPos.x + offset0.x) * frequency;</span><br><span class="line">       <span class="built_in">float</span> y0 = (wPos.y + offset0.y) * frequency;</span><br><span class="line">       <span class="built_in">float</span> z0 = (wPos.z + offset0.z) * frequency;</span><br><span class="line"></span><br><span class="line">       <span class="built_in">float</span> x1 = (wPos.x + offset1.x) * frequency * <span class="number">2</span>;</span><br><span class="line">       <span class="built_in">float</span> y1 = (wPos.y + offset1.y) * frequency * <span class="number">2</span>;</span><br><span class="line">       <span class="built_in">float</span> z1 = (wPos.z + offset1.z) * frequency * <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line">       <span class="built_in">float</span> x2 = (wPos.x + offset2.x) * frequency / <span class="number">4</span>;</span><br><span class="line">       <span class="built_in">float</span> y2 = (wPos.y + offset2.y) * frequency / <span class="number">4</span>;</span><br><span class="line">       <span class="built_in">float</span> z2 = (wPos.z + offset2.z) * frequency / <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line">       <span class="built_in">float</span> noise0 = Noise.Generate(x0, y0, z0) * amplitude;</span><br><span class="line">       <span class="built_in">float</span> noise1 = Noise.Generate(x1, y1, z1) * amplitude / <span class="number">2</span>;</span><br><span class="line">       <span class="built_in">float</span> noise2 = Noise.Generate(x2, y2, z2) * amplitude / <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line">       <span class="comment">//在采样结果上，叠加上baseHeight，限制随机生成的高度下限</span></span><br><span class="line">       <span class="keyword">return</span> Mathf.FloorToInt(noise0 + noise1 + noise2 + baseHeight);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="function">BlockType <span class="title">GenerateBlockType</span>(<span class="params">Vector3 wPos</span>)</span></span><br><span class="line">   &#123;</span><br><span class="line">       <span class="comment">//y坐标是否在Chunk内</span></span><br><span class="line">       <span class="keyword">if</span> (wPos.y &gt;= height)</span><br><span class="line">       &#123;</span><br><span class="line">           <span class="keyword">return</span> BlockType.None;</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       <span class="comment">//获取当前位置方块随机生成的高度值</span></span><br><span class="line">       <span class="built_in">float</span> genHeight = GenerateHeight(wPos);</span><br><span class="line"></span><br><span class="line">       <span class="comment">//当前方块位置高于随机生成的高度值时，当前方块类型为空</span></span><br><span class="line">       <span class="keyword">if</span> (wPos.y &gt; genHeight)</span><br><span class="line">       &#123;</span><br><span class="line">           <span class="keyword">return</span> BlockType.None;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//当前方块位置等于随机生成的高度值时，当前方块类型为草地</span></span><br><span class="line">       <span class="keyword">else</span> <span class="keyword">if</span> (wPos.y == genHeight)</span><br><span class="line">       &#123;</span><br><span class="line">           <span class="keyword">return</span> BlockType.Grass;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//当前方块位置小于随机生成的高度值 且 大于 genHeight - 5时，当前方块类型为泥土</span></span><br><span class="line">       <span class="keyword">else</span> <span class="keyword">if</span> (wPos.y &lt; genHeight &amp;&amp; wPos.y &gt; genHeight - <span class="number">5</span>)</span><br><span class="line">       &#123;</span><br><span class="line">           <span class="keyword">return</span> BlockType.Dirt;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//其他情况，当前方块类型为碎石</span></span><br><span class="line">       <span class="keyword">return</span> BlockType.Gravel;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
<p>上面这两个函数实现了生成Block信息的过程</p>
<p>在上面这段代码中我们需要注意以下几点</p>
<p>1.GenerateHeight用于通过噪音来随机生成每个方块的高度，这种随机生成的方式相比其他方式更贴近我们想要的结果。普通的随机数得到的值都是离散的，均匀分布的结果，而通过simplex noise得到的结果，会是连续的。这样会获得更加真实，接近自然的效果。</p>
<p>\2. GenerateHeight中那些数字字面量，没有特殊意义，就是经验数值，为了生成结果能够产生更多变化而已。可以自己调整试试看。</p>
<p>3.GenerateHeight中对多个噪声的生成结果进行了叠加，这是为了混合出理想的结果，具体可以网上检索查阅噪声相关资料。</p>
<p>4.GenerateBlockType内，会利用在指定位置随机生成的高度，来决定当前Block的类型。最内层是岩石，中间混杂着泥土，地表则是草地。</p>
<p>在我们有了地形元素的类型信息后，我们就可以来构建Chunk的网格，以来显示我们的Chunk了。</p>
<p>接下来我们实现BuildChunk函数</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">BuildChunk</span>(<span class="params"></span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    chunkMesh = <span class="keyword">new</span> Mesh();</span><br><span class="line">    List&lt;Vector3&gt; verts = <span class="keyword">new</span> List&lt;Vector3&gt;();</span><br><span class="line">    List&lt;Vector2&gt; uvs = <span class="keyword">new</span> List&lt;Vector2&gt;();</span><br><span class="line">    List&lt;<span class="built_in">int</span>&gt; tris = <span class="keyword">new</span> List&lt;<span class="built_in">int</span>&gt;();</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//遍历chunk, 生成其中的每一个Block</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="built_in">int</span> x = <span class="number">0</span>; x &lt; width; x++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="built_in">int</span> y = <span class="number">0</span>; y &lt; height; y++)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="built_in">int</span> z = <span class="number">0</span>; z &lt; width; z++)</span><br><span class="line">            &#123;</span><br><span class="line">                BuildBlock(x, y, z, verts, uvs, tris);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">                </span><br><span class="line">    chunkMesh.vertices = verts.ToArray();</span><br><span class="line">    chunkMesh.uv = uvs.ToArray();</span><br><span class="line">    chunkMesh.triangles = tris.ToArray();</span><br><span class="line">    chunkMesh.RecalculateBounds();</span><br><span class="line">    chunkMesh.RecalculateNormals();</span><br><span class="line">    </span><br><span class="line">    meshFilter.mesh = chunkMesh;</span><br><span class="line">    meshCollider.sharedMesh = chunkMesh;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如上所示，BuildChunk函数内部遍历了Chunk内的每一个Block,为其生成网格数据，并在最后将生成的数据（顶点，UV, 索引）提交给了chunkMesh。</p>
<p>接下来我们实现BuildBlock函数</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">BuildBlock</span>(<span class="params"><span class="built_in">int</span> x, <span class="built_in">int</span> y, <span class="built_in">int</span> z, List&lt;Vector3&gt; verts, List&lt;Vector2&gt; uvs, List&lt;<span class="built_in">int</span>&gt; tris</span>)</span></span><br><span class="line">  &#123;</span><br><span class="line">      <span class="keyword">if</span> (map[x, y, z] == <span class="number">0</span>) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">      BlockType typeid = map[x, y, z];</span><br><span class="line"></span><br><span class="line">      <span class="comment">//Left</span></span><br><span class="line">      <span class="keyword">if</span> (CheckNeedBuildFace(x - <span class="number">1</span>, y, z))</span><br><span class="line">          BuildFace(typeid, <span class="keyword">new</span> Vector3(x, y, z), Vector3.up, Vector3.forward, <span class="literal">false</span>, verts, uvs, tris);</span><br><span class="line">      <span class="comment">//Right</span></span><br><span class="line">      <span class="keyword">if</span> (CheckNeedBuildFace(x + <span class="number">1</span>, y, z))</span><br><span class="line">          BuildFace(typeid, <span class="keyword">new</span> Vector3(x + <span class="number">1</span>, y, z), Vector3.up, Vector3.forward, <span class="literal">true</span>, verts, uvs, tris);</span><br><span class="line"></span><br><span class="line">      <span class="comment">//Bottom</span></span><br><span class="line">      <span class="keyword">if</span> (CheckNeedBuildFace(x, y - <span class="number">1</span>, z))</span><br><span class="line">          BuildFace(typeid, <span class="keyword">new</span> Vector3(x, y, z), Vector3.forward, Vector3.right, <span class="literal">false</span>, verts, uvs, tris);</span><br><span class="line">      <span class="comment">//Top</span></span><br><span class="line">      <span class="keyword">if</span> (CheckNeedBuildFace(x, y + <span class="number">1</span>, z))</span><br><span class="line">          BuildFace(typeid, <span class="keyword">new</span> Vector3(x, y + <span class="number">1</span>, z), Vector3.forward, Vector3.right, <span class="literal">true</span>, verts, uvs, tris);</span><br><span class="line"></span><br><span class="line">      <span class="comment">//Back</span></span><br><span class="line">      <span class="keyword">if</span> (CheckNeedBuildFace(x, y, z - <span class="number">1</span>))</span><br><span class="line">          BuildFace(typeid, <span class="keyword">new</span> Vector3(x, y, z), Vector3.up, Vector3.right, <span class="literal">true</span>, verts, uvs, tris);</span><br><span class="line">      <span class="comment">//Front</span></span><br><span class="line">      <span class="keyword">if</span> (CheckNeedBuildFace(x, y, z + <span class="number">1</span>))</span><br><span class="line">          BuildFace(typeid, <span class="keyword">new</span> Vector3(x, y, z + <span class="number">1</span>), Vector3.up, Vector3.right, <span class="literal">false</span>, verts, uvs, tris);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="built_in">bool</span> <span class="title">CheckNeedBuildFace</span>(<span class="params"><span class="built_in">int</span> x, <span class="built_in">int</span> y, <span class="built_in">int</span> z</span>)</span></span><br><span class="line">  &#123;</span><br><span class="line">      <span class="keyword">if</span> (y &lt; <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">      <span class="keyword">var</span> type = GetBlockType(x, y, z);</span><br><span class="line">      <span class="keyword">switch</span> (type)</span><br><span class="line">      &#123;</span><br><span class="line">          <span class="keyword">case</span> BlockType.None:</span><br><span class="line">              <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">          <span class="literal">default</span>:</span><br><span class="line">              <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> BlockType <span class="title">GetBlockType</span>(<span class="params"><span class="built_in">int</span> x, <span class="built_in">int</span> y, <span class="built_in">int</span> z</span>)</span></span><br><span class="line">  &#123;</span><br><span class="line">      <span class="keyword">if</span> (y &lt; <span class="number">0</span> || y &gt; height - <span class="number">1</span>)</span><br><span class="line">      &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="comment">//当前位置是否在Chunk内</span></span><br><span class="line">      <span class="keyword">if</span> ((x &lt; <span class="number">0</span>) || (z &lt; <span class="number">0</span>) || (x &gt;= width) || (z &gt;= width))</span><br><span class="line">      &#123;</span><br><span class="line">          <span class="keyword">var</span> id = GenerateBlockType(<span class="keyword">new</span> Vector3(x, y, z) + transform.position);</span><br><span class="line">          <span class="keyword">return</span> id;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> map[x, y, z];</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
<p>（做了面优化）</p>
<p>我们的角色在地形上时，只能看到最外部的一层面，其实看不到内部的方块，所以这些看不到的方块，就没有必要浪费计算资源了。也正是这个原因，我们不能直接用正方体去随机生成，而是要像现在这样，以Face为基本单位来生成。实现这个功能的函数，便是CheckNeedBuildFace。</p>
<p>接下来让我们完成Chunk部分的最后一步</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">BuildFace</span>(<span class="params">BlockType typeid, Vector3 corner, Vector3 up, Vector3 right, <span class="built_in">bool</span> reversed, List&lt;Vector3&gt; verts, List&lt;Vector2&gt; uvs, List&lt;<span class="built_in">int</span>&gt; tris</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">int</span> index = verts.Count;</span><br><span class="line">    </span><br><span class="line">    verts.Add (corner);</span><br><span class="line">    verts.Add (corner + up);</span><br><span class="line">    verts.Add (corner + up + right);</span><br><span class="line">    verts.Add (corner + right);</span><br><span class="line">    </span><br><span class="line">    Vector2 uvWidth = <span class="keyword">new</span> Vector2(<span class="number">0.25f</span>, <span class="number">0.25f</span>);</span><br><span class="line">    Vector2 uvCorner = <span class="keyword">new</span> Vector2(<span class="number">0.00f</span>, <span class="number">0.75f</span>);</span><br><span class="line"></span><br><span class="line">    uvCorner.x += (<span class="built_in">float</span>)(typeid - <span class="number">1</span>) / <span class="number">4</span>;</span><br><span class="line">    uvs.Add(uvCorner);</span><br><span class="line">    uvs.Add(<span class="keyword">new</span> Vector2(uvCorner.x, uvCorner.y + uvWidth.y));</span><br><span class="line">    uvs.Add(<span class="keyword">new</span> Vector2(uvCorner.x + uvWidth.x, uvCorner.y + uvWidth.y));</span><br><span class="line">    uvs.Add(<span class="keyword">new</span> Vector2(uvCorner.x + uvWidth.x, uvCorner.y));</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (reversed)</span><br><span class="line">    &#123;</span><br><span class="line">        tris.Add(index + <span class="number">0</span>);</span><br><span class="line">        tris.Add(index + <span class="number">1</span>);</span><br><span class="line">        tris.Add(index + <span class="number">2</span>);</span><br><span class="line">        tris.Add(index + <span class="number">2</span>);</span><br><span class="line">        tris.Add(index + <span class="number">3</span>);</span><br><span class="line">        tris.Add(index + <span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        tris.Add(index + <span class="number">1</span>);</span><br><span class="line">        tris.Add(index + <span class="number">0</span>);</span><br><span class="line">        tris.Add(index + <span class="number">2</span>);</span><br><span class="line">        tris.Add(index + <span class="number">3</span>);</span><br><span class="line">        tris.Add(index + <span class="number">2</span>);</span><br><span class="line">        tris.Add(index + <span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这一步我们构建了正方体其中一面的网格数据，顶点，UV, 索引。这一步实现完后， 如果我们将这个组件挂在我们最初创建的Cube上，并运行，我们即会得到随机生成的一个Chunk。如下图所示：</p>
<p><img src="v2-998ea4beb691e080fb40d892db88165d_720w.jpg" alt="img"></p>
<p><img src="file:///C:\Users\admin\AppData\Roaming\Tencent\Users\1399130811\QQ\WinTemp\RichOle\821K(9G_L@R3HT(LDAF9V70.png" alt="img"><img src="C:/Users/admin/Desktop/821K(9G_L@R3HT(LDAF9V70.png" alt="821K(9G_L@R3HT(LDAF9V70"><img src="C:/Users/admin/Desktop/821K(9G_L@R3HT(LDAF9V70.png" alt="821K(9G_L@R3HT(LDAF9V70"><img src="sdf.png" alt="sdf"></p>
<p>地图场景初步搭建成功</p>
<p>下一步 让敌人在起点生成然后沿着路走向终点即可</p>
<p>那么我们就设计成在起点坐标 每隔4s生成1个怪物（怪物总数待定） </p>
<p>下一步 让召唤出的敌人按我们给定的路线前进</p>
<p>1创建空物体，在空物体里创建多个路径目标点。自定义脚本：RoadPoints</p>
<p>public class CreateEnemies : MonoBehaviour<br>{<br>    public int enemiesCount;<br>    /// <summary>
    /// 敌人
    /// </summary><br>    public GameObject Enemy;<br>    private int time = 1;<br>    // Start is called before the first frame update<br>    void Start()<br>    {</p>
<pre><code>&#125;

// Update is called once per frame
void Update()
&#123;
    time++;
    //每隔120帧召唤一个敌人
    if(time&gt;120)
    &#123;
        time = 0;
        Instantiate(Enemy, this.transform.position, this.transform.rotation);
    &#125;
&#125;
</code></pre><p>}</p>
<p>2.给移动物体Player自定义脚本</p>
<h3 id="Cinemachine-导入即可"><a href="#Cinemachine-导入即可" class="headerlink" title="Cinemachine 导入即可"></a>Cinemachine 导入即可</h3><p> <img src="image-20220604125533161.png" alt="image-20220604125533161"></p>
<p>二、添加移动轨道</p>
<p>Cinemachine中的CinemachineSmoothPath可以用来设计固定路线移动方案API参考<br>TrackAsset：<a target="_blank" rel="noopener" href="https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackAsset.html">https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackAsset.html</a><br>TrackBindingTypeAttribute：<a target="_blank" rel="noopener" href="https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackBindingTypeAttribute.html">https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackBindingTypeAttribute.html</a><br>TrackClipTypeAttribute：<br><a target="_blank" rel="noopener" href="https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackClipTypeAttribute.html">https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackClipTypeAttribute.html</a><br>TrackColorAttribute：<a target="_blank" rel="noopener" href="https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackColorAttribute.html">https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Timeline.TrackColorAttribute.html</a><br>————————————————<br>版权声明：本文为CSDN博主「至肝主义圈毛君」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/Ha1f_Awake/article/details/101754700">https://blog.csdn.net/Ha1f_Awake/article/details/101754700</a></p>
<p><img src="image-20220604133218784.png" alt="image-20220604133218784"></p>
<p><img src="image-20220604133606275.png" alt="image-20220604133606275"></p>
<p>三、简单的移动逻辑（cube沿设计的路线移动）</p>
<p>public class EnemyMove : MonoBehaviour<br>{<br>    public GameObject join;<br>    public float m_Speed = 10;<br>    public CinemachineSmoothPath m_Path;</p>
<pre><code>private float m_Position = 0;
public PositionUnits m_type = PositionUnits.Distance;
public UpdateMethod m_method = UpdateMethod.SmartUpdate;

public Waypoint[] point;
void Start()
&#123;
    point = m_Path.m_Waypoints;
&#125;
void FixedUpdate()
&#123;
    if (m_method == UpdateMethod.FixedUpdate)
        SetCartPosition(m_Position + m_Speed * Time.deltaTime);


&#125;
void Update()
&#123;
    float speed = Application.isPlaying ? m_Speed : 0;
    if (m_method == UpdateMethod.SmartUpdate)
        SetCartPosition(m_Position + speed * Time.deltaTime);
&#125;
void LateUpdate()
&#123;
    if (!Application.isPlaying)
        SetCartPosition(m_Position);
    else if (m_method == UpdateMethod.LateUpdate)
        SetCartPosition(m_Position + m_Speed * Time.deltaTime);
&#125;
void SetCartPosition(float distanceAlongPath)
&#123;
    m_Position = m_Path.StandardizeUnit(distanceAlongPath， m_type);
    transform.position = m_Path.EvaluatePositionAtUnit(m_Position， m_type); transform.rotation = m_Path.EvaluateOrientationAtUnit(m_Position， m_type);
&#125;
</code></pre><p>}</p>
<p>将其绑定到预制体上（轨迹也要绑定）</p>
<p><img src="]HHLV8%SMAX${SOU{IDOBCC.png" alt="img"></p>
<p>下一步 设计qq人到达终点消失的方法</p>
<p>对象到达终点后 逐渐消失</p>
<p>为终点添加碰撞检测</p>
<p>public class Enemies : MonoBehaviour<br>{<br>    public GameObject join;<br>    // Start is called before the first frame update<br>    void Start()<br>    {</p>
<pre><code>&#125;

// Update is called once per frame
void Update()
&#123;

&#125;//碰撞开始  
void OnCollisionEnter(Collision collision)
&#123;
    if (collision.gameObject.name == &quot;Sphere&quot;)
    &#123;
        Destroy(collision.gameObject);
    &#125;
&#125;
</code></pre><p>}</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2022/03/08/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%BC%80%E5%8F%91%E6%B8%B8%E6%88%8F%E9%80%89%E6%8B%A9%E7%95%8C%E9%9D%A2%20-%20%E5%89%AF%E6%9C%AC/" data-id="cl403sxsd003zf8vu7okj583m" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/notes-on-computer-expertise/2022/03/10/%E4%BB%A3%E7%A0%81%E5%AE%9E%E6%88%98/%E5%9B%9B%E5%9B%BD%E8%B1%A1%E6%A3%8Bai/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          (no title)
        
      </div>
    </a>
  
  
    <a href="/notes-on-computer-expertise/2022/02/27/%E7%82%89%E7%9F%B3%E4%BC%A0%E8%AF%B4/Untitled%20Folder/unity%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B%20%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title"></div>
    </a>
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C#工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C++工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/Mysql/">Mysql</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/blender/">blender</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/linux/">linux</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/manim/">manim</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/spring/">spring</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C/">vba基础操作</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E5%88%9B%E9%80%A0%E6%A8%A1%E5%BC%8F/">创造模式</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">操作系统基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/">操作系统开发</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E5%AD%A6/">数学</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">数据结构基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%A8%A1%E6%9D%BF/">模板</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">深度学习</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%8B%B1%E8%AF%AD/">英语</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%99%9A%E5%B9%BB4/">虚幻4</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86/">计算机组成原理</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/">计算机网络</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/notes-on-computer-expertise/tags/C/" rel="tag">C++</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/notes-on-computer-expertise/tags/C/" style="font-size: 10px;">C++</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/05/">May 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/03/">March 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/02/">February 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/01/">January 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2021/12/">December 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/31/vue/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E9%AA%8C%E8%AF%81%E7%A0%81%E6%97%A0%E6%B3%95%E6%98%BE%E7%A4%BA/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/26/%E6%95%B0%E6%8D%AE%E5%BA%93/navicat%E5%AE%89%E8%A3%85/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/25/%E8%99%9A%E5%B9%BB4%E5%BC%95%E6%93%8E%E5%BC%80%E5%8F%91/%E8%99%9A%E5%B9%BB%E5%9B%9B%20mod%E5%88%B6%E4%BD%9C/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/python/python%E6%89%B9%E9%87%8F%E7%94%9F%E6%88%90%E6%95%B0%E6%8D%AE/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C%E7%AC%94%E8%AE%B0/EXCEL%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2022 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/notes-on-computer-expertise/" class="mobile-nav-link">Home</a>
  
    <a href="/notes-on-computer-expertise/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/notes-on-computer-expertise/js/jquery-3.4.1.min.js"></script>



  
<script src="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.js"></script>




<script src="/notes-on-computer-expertise/js/script.js"></script>





  </div>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        tex2jax: {
            inlineMath: [ ["$","$"], ["\\(","\\)"] ],
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
            processEscapes: true
        }
    });
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax();
        for (var i = 0; i < all.length; ++i)
            all[i].SourceElement().parentNode.className += ' has-jax';
    });
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</body>
</html>